package com.xjx.account.service.impl;

import com.xjx.common.constant.RedisKey;
import com.xjx.common.enums.BizCodeEnum;
import com.xjx.common.enums.SendCodeEnum;
import com.xjx.common.util.CheckUtil;
import com.xjx.common.util.CommonUtil;
import com.xjx.common.util.JsonData;
import lombok.extern.slf4j.Slf4j;
import com.xjx.account.component.SmsComponent;
import com.xjx.account.config.SmsConfig;
import com.xjx.account.service.NotifyService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.internet.MimeMessage;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class NotifyServiceImpl implements NotifyService {

    /**
     * 10分钟有效
     */
    private static final int CODE_EXPIRED = 60*1000*10;

    @Autowired
    private SmsComponent smsComponent;

    @Autowired
    private SmsConfig smsConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private TemplateEngine templateEngine;

    @Value("${spring.mail.username}")
    private String from;

    @Override
    public boolean sendVerificationEmail(String to, String subject, String code, String type) {
        try {
            // 准备Thymeleaf模板上下文
            Context context = new Context();
            context.setVariable("code", code);
            context.setVariable("type", type);
            context.setVariable("time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            // 处理模板生成HTML内容
            String htmlContent = templateEngine.process("email/verification-code", context);

            // 创建MIME消息
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(from);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);

            // 发送邮件
            mailSender.send(message);
            log.info("邮件发送成功：{}", to);
            return true;
        } catch (Exception e) {
            log.error("邮件发送失败", e);
            return false;
        }
    }




    @Override
    public boolean sendEmailCode(String email, String type) {
        try {
            // 生成6位随机验证码
            String code = CommonUtil.getRandomCode(6);

            // 将验证码存入Redis缓存，使用与其他验证码相同的格式
            String cacheKey = String.format(RedisKey.CHECK_CODE_KEY, type, email);
            String value = code + "_" + CommonUtil.getCurrentTimestamp();
            redisTemplate.opsForValue().set(cacheKey, value, CODE_EXPIRED, TimeUnit.MILLISECONDS);

            // 验证码类型对应的邮件主题
            String subject;
            switch (type) {
                case "login":
                    subject = "登录验证码";
                    break;
                case "register":
                    subject = "注册验证码";
                    break;
                case "reset":
                    subject = "重置密码验证码";
                    break;
                default:
                    subject = "验证码";
            }

            // 使用邮件服务发送验证码
            return sendVerificationEmail(email, subject, code, type);
        } catch (Exception e) {
            log.error("发送邮箱验证码失败", e);
            return false;
        }
    }

    @Override
    public String getEmailCode(String email, String type) {
        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY, type, email);
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if (StringUtils.isNotBlank(cacheValue)) {
            return cacheValue.split("_")[0];
        }
        return null;
    }

    @Override
    public void removeEmailCode(String email, String type) {
        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY, type, email);
        redisTemplate.delete(cacheKey);
    }



    @Override
    public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {

        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY,sendCodeEnum.name(),to);

        String cacheValue = redisTemplate.opsForValue().get(cacheKey);

        //如果不为空，再判断是否是60秒内重复发送 0122_232131321314132
        if(StringUtils.isNotBlank(cacheValue)){
            long ttl = Long.parseLong(cacheValue.split("_")[1]);
            //当前时间戳-验证码发送的时间戳，如果小于60秒，则不给重复发送
            long leftTime = CommonUtil.getCurrentTimestamp() - ttl;
            if( leftTime < (1000*60)){
                log.info("重复发送短信验证码，时间间隔:{}秒",leftTime);
                return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
            }
        }

        String code = CommonUtil.getRandomCode(6);
        //生成拼接好验证码
        String value = code+"_"+CommonUtil.getCurrentTimestamp();
        redisTemplate.opsForValue().set(cacheKey,value,CODE_EXPIRED,TimeUnit.MILLISECONDS);

        if(CheckUtil.isEmail(to)){
            //发送邮箱验证码
            sendVerificationEmail(to, "验证码", code, sendCodeEnum.name());
        }else if(CheckUtil.isPhone(to)){

            //发送手机验证码
            smsComponent.send(to,smsConfig.getTemplateId(),code);
        }
        return JsonData.buildSuccess();
    }

    /**
     * 验证码校验逻辑
     * @param sendCodeEnum
     * @param to
     * @param code
     * @return
     */
    @Override
    public boolean checkCode(SendCodeEnum sendCodeEnum, String to, String code) {

        String cacheKey = String.format(RedisKey.CHECK_CODE_KEY,sendCodeEnum.name(),to);

        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if(StringUtils.isNotBlank(cacheValue)){

            String cacheCode = cacheValue.split("_")[0];
            if(cacheCode.equalsIgnoreCase(code)){
                //删除验证码
                redisTemplate.delete(cacheKey);
                return true;
            }

        }

        return false;
    }
}

